package com.car.loan.project.xr.service.impl;

import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.car.loan.common.SnowflakeIdWorker;
import com.car.loan.common.exception.loan.LoanParameterException;
import com.car.loan.common.utils.BeanUtils;
import com.car.loan.common.utils.IdCardUtil;
import com.car.loan.common.utils.LocalDateUtil;
import com.car.loan.common.utils.SecurityUtils;
import com.car.loan.common.utils.StringUtils;
import com.car.loan.common.utils.qiniu.QiniuUtil;
import com.car.loan.framework.aspectj.lang.annotation.DataScope;
import com.car.loan.framework.web.domain.AjaxResult;
import com.car.loan.project.cd.domain.CdCredit;
import com.car.loan.project.cd.domain.vo.CreditAlbumVo;
import com.car.loan.project.cd.mapper.CdCreditMapper;
import com.car.loan.project.cd.util.enums.CreditStatus;
import com.car.loan.project.cm.domain.CmBank;
import com.car.loan.project.cm.domain.CmBankScheme;
import com.car.loan.project.cm.mapper.CmBankMapper;
import com.car.loan.project.cm.mapper.CmBankSchemeMapper;
import com.car.loan.project.system.domain.SysUser;
import com.car.loan.project.system.service.ISysSequenceService;
import com.car.loan.project.ve.domain.VeVehicleAlbum;
import com.car.loan.project.ve.domain.VeVehicleEvaluation;
import com.car.loan.project.ve.mapper.VeVehicleAlbumMapper;
import com.car.loan.project.ve.mapper.VeVehicleEvaluationMapper;
import com.car.loan.project.xr.domain.Customer;
import com.car.loan.project.xr.domain.CustomerDetail;
import com.car.loan.project.xr.domain.CustomerGuarantor;
import com.car.loan.project.xr.domain.CustomerSpouse;
import com.car.loan.project.xr.domain.Loan;
import com.car.loan.project.xr.domain.LoanAlbum;
import com.car.loan.project.xr.domain.LoanCar;
import com.car.loan.project.xr.domain.LoanContact;
import com.car.loan.project.xr.domain.LoanDetail;
import com.car.loan.project.xr.domain.LoanExt;
import com.car.loan.project.xr.domain.LoanInsurance;
import com.car.loan.project.xr.domain.LoanModifyInfo;
import com.car.loan.project.xr.domain.LoanStatus;
import com.car.loan.project.xr.mapper.CustomerDetailMapper;
import com.car.loan.project.xr.mapper.CustomerGuarantorMapper;
import com.car.loan.project.xr.mapper.CustomerMapper;
import com.car.loan.project.xr.mapper.CustomerSpouseMapper;
import com.car.loan.project.xr.mapper.LoanAlbumMapper;
import com.car.loan.project.xr.mapper.LoanCarMapper;
import com.car.loan.project.xr.mapper.LoanContactMapper;
import com.car.loan.project.xr.mapper.LoanDetailMapper;
import com.car.loan.project.xr.mapper.LoanExtMapper;
import com.car.loan.project.xr.mapper.LoanInsuranceMapper;
import com.car.loan.project.xr.mapper.LoanMapper;
import com.car.loan.project.xr.mapper.LoanModifyInfoMapper;
import com.car.loan.project.xr.mapper.LoanStatusMapper;
import com.car.loan.project.xr.service.ILoanService;
import com.car.loan.project.xr.util.RedisDataUtil;
import com.car.loan.project.xr.util.bo.business.CustomerAddBo;
import com.car.loan.project.xr.util.bo.business.CustomerContactAddBo;
import com.car.loan.project.xr.util.bo.business.CustomerGuarantorAddBo;
import com.car.loan.project.xr.util.bo.business.CustomerInfoAddBo;
import com.car.loan.project.xr.util.bo.business.CustomerSpouseAddBo;
import com.car.loan.project.xr.util.bo.business.LoanAddBo;
import com.car.loan.project.xr.util.bo.business.LoanAddCarBo;
import com.car.loan.project.xr.util.bo.business.LoanAddDetailBo;
import com.car.loan.project.xr.util.bo.business.LoanAddExtBo;
import com.car.loan.project.xr.util.bo.business.LoanAlbumBo;
import com.car.loan.project.xr.util.bo.business.LoanBaseAddBo;
import com.car.loan.project.xr.util.bo.business.LoanBaseInfo;
import com.car.loan.project.xr.util.bo.business.LoanBo;
import com.car.loan.project.xr.util.bo.business.LoanDataAuditBo;
import com.car.loan.project.xr.util.bo.business.LoanUpdateBo;
import com.car.loan.project.xr.util.bo.business.modify.LoanModifyBo;
import com.car.loan.project.xr.util.bo.business.modify.LoanModifyFiledBo;
import com.car.loan.project.xr.util.bo.business.modify.LoanModifyInfoBo;
import com.car.loan.project.xr.util.bo.business.modify.LoanModifyPageParam;
import com.car.loan.project.xr.util.enums.BusinessApostilleStatus;
import com.car.loan.project.xr.util.enums.CustomerMarry;
import com.car.loan.project.xr.util.enums.LoanAlbumType;
import com.car.loan.project.xr.util.enums.LoanBusinessAuditStatus;
import com.car.loan.project.xr.util.enums.LoanBusinessStatus;
import com.car.loan.project.xr.util.enums.RepaymentInfoStatus;
import com.car.loan.project.xr.util.repayment.RepaymentFormulaInterface;
import com.car.loan.project.xr.util.repayment.RepaymentInfo;
import com.car.loan.project.xr.util.repayment.RepaymentInfoParam;
import com.car.loan.project.xr.util.select.LoanBasePageParam;
import com.car.loan.project.xr.util.vo.BusinessAuditDetailVo;
import com.car.loan.project.xr.util.vo.BusinessAuditInfo;
import com.car.loan.project.xr.util.vo.BusinessDetailVo;
import com.car.loan.project.xr.util.vo.LoanAlbumVo;
import com.car.loan.project.xr.util.vo.LoanApplyVo;
import com.car.loan.project.xr.util.vo.LoanContractAuditVo;
import com.car.loan.project.xr.util.vo.LoanContractAuditVo.FileInfo;
import com.car.loan.project.xr.util.vo.LoanDetailVo.BusinessInfoVo;
import com.car.loan.project.xr.util.vo.LoanDetailVo.CarEvaluationInfo;
import com.car.loan.project.xr.util.vo.LoanDetailVo.CreditInfo;
import com.car.loan.project.xr.util.vo.LoanDetailVo.LoanBaseInfoVo;
import com.car.loan.project.xr.util.vo.modify.LoanModifyDetail;
import com.car.loan.project.xr.util.vo.modify.LoanModifyDetail.BaseInfo;
import com.car.loan.project.xr.util.vo.modify.LoanModifyDetail.BusinessInfo;
import com.car.loan.project.xr.util.vo.modify.LoanModifyDetail.CustomerInfo;
import com.car.loan.project.xr.util.vo.modify.LoanModifyDetail.RepayInfo;
import com.google.common.collect.Lists;
import java.math.BigDecimal;
import java.math.MathContext;
import java.time.LocalDateTime;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.stream.Collectors;
import javax.annotation.Resource;
import javax.validation.Valid;
import javax.validation.constraints.NotNull;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

/**
 * 贷款Service业务层处理
 *
 * @author ruoyi
 * @date 2019-11-03
 */
@Service
public class LoanServiceImpl implements ILoanService {

    @Autowired
    private LoanMapper loanMapper;

    @Autowired
    private SnowflakeIdWorker snowflakeIdWorker;

    @Autowired
    private CustomerMapper customerMapper;

    @Autowired
    private CustomerDetailMapper customerDetailMapper;

    @Autowired
    private CustomerSpouseMapper customerSpouseMapper;

    @Autowired
    private CustomerGuarantorMapper customerGuarantorMapper;

    @Autowired
    private LoanContactMapper loanContactMapper;

    @Autowired
    private LoanCarMapper loanCarMapper;

    @Autowired
    private LoanExtMapper loanExtMapper;

    @Autowired
    private LoanDetailMapper loanDetailMapper;

    @Autowired
    private LoanAlbumMapper loanAlbumMapper;

    @Autowired
    private LoanStatusMapper loanStatusMapper;

    @Autowired
    private ISysSequenceService sequenceBusinessServiceImpl;

    @Autowired
    private QiniuUtil qiniuUtil;

    @Autowired
    private RedisDataUtil redisDataUtil;

    @Autowired
    private VeVehicleEvaluationMapper veVehicleEvaluationMapper;
    @Autowired
    private VeVehicleAlbumMapper veVehicleAlbumMapper;

    @Autowired
    private CdCreditMapper cdCreditMapper;

    @Autowired
    private LoanInsuranceMapper loanInsuranceMapper;

    @Autowired
    private CmBankSchemeMapper cmBankSchemeMapper;

    @Autowired
    private CmBankMapper cmBankMapper;


    @Autowired
    private Map<String, RepaymentFormulaInterface> repaymentFormulaInterfaceMap;


    @Override
    @DataScope(deptAlias = "d", userAlias = "u")
    public Page<LoanBaseInfo> page(LoanBasePageParam loanBasePageParam) {
        Page page = new Page(loanBasePageParam.getPageNum(), loanBasePageParam.getPageSize());
        return loanMapper.findLoanBasePage(page, loanBasePageParam);
    }


    @Override
    @DataScope(deptAlias = "d", userAlias = "u")
    public Page<?> modifyPage(LoanModifyPageParam loanModifyPageParam) {
        Page page = new Page(loanModifyPageParam.getPageNum(), loanModifyPageParam.getPageSize());
        return loanMapper.findLoanModifyPage(page, loanModifyPageParam);
    }

    /**
     * 查询贷款
     *
     * @param id 贷款ID
     * @return 贷款
     */
    @Override
    public Loan selectLoanById(Long id) {
        return loanMapper.selectById(id);
    }


    @Override
    @Transactional(rollbackFor = Exception.class)
    public AjaxResult apply(LoanBo loanBo) {
        long customerId = snowflakeIdWorker.nextId();
        long loanId = snowflakeIdWorker.nextId();
        //处理用户信息
        saveCustomer(loanBo.getCustomerInfo(), loanId, customerId, false);
        //处理业务数据
        saveLoan(loanBo.getLoanInfo(), loanId, customerId, false, loanBo.getOperatorStatus());
        //业务状态
        LoanStatus loanStatus = new LoanStatus();
        loanStatus.setBusinessStatus(loanBo.getOperatorStatus());
        loanStatus.setBusinessAuditStatus((long) LoanBusinessAuditStatus.INIT.status);
        loanStatus.setLoanId(loanId);
        loanStatus.setBusinessAdminId(SecurityUtils.getLoginUserId());
        loanStatus.setBusinessTime(LocalDateTime.now());
        loanStatusMapper.insert(loanStatus);
        return AjaxResult.success();
    }


    @Override
    public AjaxResult audit(BusinessAuditInfo businessAuditInfo) {
        @NotNull Long loanId = businessAuditInfo.getLoanId();
        Optional<LoanStatus> optionalLoanStatus = loanStatusMapper.selectByLoanId(loanId);
        LoanStatus loanStatus = optionalLoanStatus
            .orElseThrow(() -> new LoanParameterException("该业务状态数据异常，请联系管理员"));
        if (LoanBusinessAuditStatus.INIT.status != loanStatus.getBusinessAuditStatus()) {
            return AjaxResult.error("当前状态不可再次提交");
        }

        if (LoanBusinessStatus.INIT.status == loanStatus.getBusinessStatus()) {
            return AjaxResult.error("业务申请还未提交");
        }

        Optional<Loan> optionalLoan
            = Optional.ofNullable(loanMapper.selectById(loanId));
        Loan loan = optionalLoan.orElseThrow(() -> new LoanParameterException("无该业务数据"));
        Optional<LoanDetail> optionalLoanDetail = loanDetailMapper.selectByLoanId(loanId);
        LoanDetail loanDetail = optionalLoanDetail
            .orElseThrow(() -> new LoanParameterException("业务数据详情信息异常"));
        loanDetail.setAuditRemark(businessAuditInfo.getAuditRemark());
        loanDetail.setMissingRemark(businessAuditInfo.getMissingRemark());
        loanDetail.setBusinessSuggest(businessAuditInfo.getBusinessSuggest());
        loanDetailMapper.updateById(loanDetail);
        if (LoanBusinessAuditStatus.APOSTILLE.status == businessAuditInfo.getResult()) {
            if (null == businessAuditInfo.getSecondAuditId()
                || businessAuditInfo.getSecondAuditId() == 0) {
                return AjaxResult.error("请选择加签人");
            }
            loan.setSecondAuditId(businessAuditInfo.getSecondAuditId());
        }
        loan.setSecondAuditId(businessAuditInfo.getSecondAuditId());
        loanMapper.updateById(loan);

        loanStatus.setBusinessAuditId(SecurityUtils.getLoginUserId());
        loanStatus.setBusinessAuditTime(LocalDateTime.now());
        loanStatus.setBusinessAuditStatus(businessAuditInfo.getResult());
        loanStatus.setBusinessApostilleStatus((long) BusinessApostilleStatus.INIT.status);

        loanStatusMapper.updateById(loanStatus);
        return AjaxResult.success();
    }


    @Override
    public AjaxResult apostilleAudit(BusinessAuditInfo businessAuditInfo) {

        @NotNull Long loanId = businessAuditInfo.getLoanId();
        Optional<LoanStatus> optionalLoanStatus = loanStatusMapper.selectByLoanId(loanId);
        LoanStatus loanStatus = optionalLoanStatus
            .orElseThrow(() -> new LoanParameterException("该业务状态数据异常，请联系管理员"));
        if (BusinessApostilleStatus.INIT.status != loanStatus.getBusinessApostilleStatus()) {
            return AjaxResult.error("当前状态不可再次提交");
        }
        Optional<LoanDetail> optionalLoanDetail = loanDetailMapper.selectByLoanId(loanId);
        LoanDetail loanDetail = optionalLoanDetail
            .orElseThrow(() -> new LoanParameterException("业务数据详情信息异常"));
        loanDetail.setAuditRemark(businessAuditInfo.getAuditRemark());
        loanDetail.setMissingRemark(businessAuditInfo.getMissingRemark());
        loanDetail.setBusinessSuggest(businessAuditInfo.getBusinessSuggest());
        loanDetail.setSecondAuditRemark(businessAuditInfo.getSecondAuditRemark());
        loanDetailMapper.updateById(loanDetail);

        loanStatus.setBusinessApostilleId(SecurityUtils.getLoginUserId());
        loanStatus.setBusinessApostilleTime(LocalDateTime.now());
        loanStatus.setBusinessApostilleStatus(businessAuditInfo.getSecondResult());
        loanStatusMapper.updateById(loanStatus);
        return AjaxResult.success();
    }

    private void saveLoan(@Valid LoanAddBo loanAddBo, long loanId, long customerId, boolean isOld,
        long operatorStatus) {
        LoanBaseAddBo loanInfo = loanAddBo.getLoanBase();
        Loan loan = new Loan();
        BeanUtils.copyBeanProp(loan, loanInfo);
        loan.setId(loanId);
        Long loginUserId = SecurityUtils.getLoginUserId();
        loan.setModifyId(loginUserId);
        loan.setModifyTime(LocalDateTime.now());
        loan.setBusinessStatus(com.car.loan.project.xr.util.enums.LoanStatusEnum.AUDIT.status);
        if (operatorStatus == com.car.loan.project.xr.util.enums.LoanStatusEnum.INIT.status) {
            loan.setBusinessStatus(com.car.loan.project.xr.util.enums.LoanStatusEnum.INIT.status);
        }
        if (isOld) {
            loanMapper.updateById(loan);
        } else {
            loan.setBusinessNo(sequenceBusinessServiceImpl.next());
            loan.setCustomerId(customerId);
            loan.setCreateTime(LocalDateTime.now());
            loan.setCreatorId(loginUserId);
            loanMapper.insert(loan);
        }

        //删除业务相关数据
        if (isOld) {
            loanInsuranceMapper.delete(new QueryWrapper<>(new LoanInsurance().setLoanId(loanId)));
            loanCarMapper.delete(new QueryWrapper<>(new LoanCar().setLoanId(loanId)));
            loanExtMapper.delete(new QueryWrapper<>(new LoanExt().setLoanId(loanId)));
            loanAlbumMapper.delete(new QueryWrapper<>(new LoanAlbum().setLoanId(loanId)));
        }
        if (isOld) {
            //业务扩展数据
            Optional<LoanDetail> optionalLoanDetail = loanDetailMapper.selectByLoanId(loanId);
            if (optionalLoanDetail.isPresent()) {
                LoanDetail loanDetail = optionalLoanDetail.get();
                loanDetail.setRemark(loanAddBo.getLoanDetail().getRemark());
                loanDetailMapper.updateById(loanDetail);
            } else {
                //业务扩展数据
                LoanDetail loanDetail = new LoanDetail();
                loanDetail.setRemark(loanAddBo.getLoanDetail().getRemark());
                loanDetail.setLoanId(loanId);
                loanDetailMapper.insert(loanDetail);
            }
        } else {
            //业务扩展数据
            LoanDetail loanDetail = new LoanDetail();
            loanDetail.setRemark(loanAddBo.getLoanDetail().getRemark());
            loanDetail.setLoanId(loanId);
            loanDetailMapper.insert(loanDetail);
        }

        //业务车辆数据
        saveLoanCar(loanAddBo.getLoanCar(), loanId);
        //处理业务数据
        saveLoanExt(loanAddBo.getLoanExt(), loanId);
        //处理附件信息
        saveLoanAlbum(loanAddBo.getLoanDetail(), loanId);
        //保存业务保险信息
        LoanInsurance loanInsurance = new LoanInsurance();
        loanInsurance.setLoanId(loanId);
        loanInsurance.setStatus(1);
        loanInsuranceMapper.insert(loanInsurance);
    }


    private void saveLoanAlbum(@Valid LoanAddDetailBo loanAddDetailBo, long loanId) {
        saveAlbum(loanAddDetailBo.getContractImages(), LoanAlbumType.CONTRACT.type, loanId);
        saveAlbum(loanAddDetailBo.getCreditImages(), LoanAlbumType.CREDIT.type, loanId);
        saveAlbum(loanAddDetailBo.getFaceSignImages(), LoanAlbumType.FACE_SIGN.type, loanId);
        saveAlbum(loanAddDetailBo.getHomeImages(), LoanAlbumType.HOME.type, loanId);
        saveAlbum(loanAddDetailBo.getVideos(), LoanAlbumType.VIDEOS.type, loanId);
        saveAlbum(loanAddDetailBo.getPdf(), LoanAlbumType.PDF.type, loanId);


    }

    private void saveAlbum(@Valid List<CreditAlbumVo> creditAlbumVos, Integer type, long loanId) {
        if (StringUtils.isNotEmpty(creditAlbumVos)) {
            for (CreditAlbumVo creditAlbumVo : creditAlbumVos) {
                LoanAlbum loanAlbum = new LoanAlbum();
                loanAlbum.setLoanId(loanId);
                loanAlbum.setType(type);
                loanAlbum.setUrl(creditAlbumVo.getUrl());
                loanAlbumMapper.insert(loanAlbum);
            }
        }

    }

    private void saveLoanExt(@Valid LoanAddExtBo loanAddExtBo, long loanId) {
        LoanExt loanExt = new LoanExt();
        BeanUtils.copyBeanProp(loanExt, loanAddExtBo);
        loanExt.setLoanId(loanId);
        loanExtMapper.insert(loanExt);
    }

    private void saveLoanCar(@Valid LoanAddCarBo carBo, long loanId) {
        LoanCar loanCar = new LoanCar();
//        if (null == carBo.getCarNature()) {
//            throw new LoanParameterException("选择车辆性质");
//
//        }
//        if (CarNature.SECOND_CAR.nature == carBo.getCarNature()) {
//            if (StringUtils.isEmpty(carBo.getFrameNo())) {
//                throw new LoanParameterException("请输入车架号");
//            }
//        }
        BeanUtils.copyBeanProp(loanCar, carBo);
        loanCar.setType(carBo.getCarModel());
        loanCar.setLoanId(loanId);
        loanCarMapper.insert(loanCar);
    }

    public static void main(String[] args) {
        String json = "{\n"
            + "\"plateType\": \"公牌\",\n"
            + "\"carNature\": 2,\n"
            + "\"registProvince\": \"浙江省\",\n"
            + "\"registCity\": \"宁波\",\n"
            + "\"frameNo\": \"LJDKAA241E0154881\",\n"
            + "\"engineNo\": \"0W050071\",\n"
            + "\"carModel\": \"起亚牌YQZ7204A\",\n"
            + "\"carType\": \"小型轿车\",\n"
            + "\"brand\": \"长城\"\n"
            + "}";
        LoanAddCarBo loanAddCarBo = JSON.parseObject(json, LoanAddCarBo.class);
        LoanCar loanCar = new LoanCar();
        BeanUtils.copyBeanProp(loanCar, loanAddCarBo);
        System.out.println();

    }


    /**
     * @param isOld 是否是老数据
     */
    private void saveCustomer(@Valid CustomerAddBo customerAddBo, long loanId, long customerId,
        boolean isOld) {

        Optional<CustomerAddBo> optionalCustomerAddBo = Optional.ofNullable(customerAddBo);

        //客户基本信息
        CustomerInfoAddBo customerInfo = optionalCustomerAddBo.map(CustomerAddBo::getCustomerInfo)
            .get();

        String idCardNo = optionalCustomerAddBo
            .map(CustomerAddBo::getCustomerInfo).map(CustomerInfoAddBo::getIdCardNo)
            .orElseThrow(() -> new LoanParameterException("请输入客户身份证号码"));
        if (!IdCardUtil.idCardValidate(idCardNo)) {
            throw new LoanParameterException("客户身份证号码格式错误");
        }
        Customer customer = new Customer();
        BeanUtils.copyBeanProp(customer, customerInfo);
        customer.setId(customerId);
        if (isOld) {
            customerMapper.updateById(customer);
        } else {
            customerMapper.insert(customer);
        }

        //删除客户其他信息
        if (isOld) {
            customerDetailMapper
                .delete(new QueryWrapper<>(new CustomerDetail().setCustomerId(customerId)));
            customerSpouseMapper
                .delete(new QueryWrapper<>(new CustomerSpouse().setCustomerId(customerId)));
            customerGuarantorMapper
                .delete(new QueryWrapper<>(new CustomerGuarantor().setLoanId(loanId)));
            loanContactMapper.delete(new QueryWrapper<>(new LoanContact().setLoanId(loanId)));
        }

        //客户扩展信息
        CustomerDetail customerDetail = new CustomerDetail();
        BeanUtils.copyBeanProp(customerDetail, customerInfo);
        customerDetail.setSex(IdCardUtil.getSex(idCardNo));
        customerDetail.setCustomerId(customerId);
        customerDetailMapper.insert(customerDetail);
        Integer marry = customerInfo.getMarry();
        //处理配偶
        if (null != marry && CustomerMarry.MARRIED.status == marry) {
            saveCustomerSpouse(customerAddBo.getCustomerSpouse(), customerId);
        }
        //处理担保人
        saveCustomerGuarantor(customerAddBo.getCustomerGuarantors(), loanId);
        //处理紧急联系人
        saveCustomerContact(customerAddBo.getCustomerContacts(), loanId);
    }

    private void saveCustomerContact(@Valid List<CustomerContactAddBo> customerContacts,
        long loanId) {
//        if (StringUtils.isEmpty(customerContacts)) {
//            throw new LoanParameterException(
//                "未填写客户紧急联系人");
//        }
//        if (customerContacts.size() < 2) {
//            throw new LoanParameterException(
//                "客户紧急联系人信息未填写完整");
//        }

        for (CustomerContactAddBo customerContact : customerContacts) {
            LoanContact loanContact = new LoanContact();
            if (StringUtils.isEmpty(customerContact.getName()) || StringUtils
                .isEmpty(customerContact.getMobile())) {
                throw new LoanParameterException(
                    "客户紧急联系人信息未填写完整");
            }
            BeanUtils.copyBeanProp(loanContact, customerContact);
            loanContact.setLoanId(loanId);
            loanContactMapper.insert(loanContact);
        }


    }


    private void saveCustomerGuarantor(@Valid List<CustomerGuarantorAddBo> customerGuarantors,
        final long loanId) {
        if (StringUtils.isNotEmpty(customerGuarantors)) {
            for (CustomerGuarantorAddBo customerGuarantorAddBo : customerGuarantors) {
                CustomerGuarantor customerGuarantor = new CustomerGuarantor();
                BeanUtils.copyBeanProp(customerGuarantor, customerGuarantorAddBo);
                String idCardNo = customerGuarantorAddBo.getIdCardNo();
                if (!IdCardUtil.idCardValidate(idCardNo)) {
                    throw new LoanParameterException(
                        "客户担保人'" + customerGuarantorAddBo.getName() + "'身份证号码格式错误");
                }
                if (StringUtils.isEmpty(customerGuarantorAddBo.getAddress())) {
                    throw new LoanParameterException(
                        "客户担保人'" + customerGuarantorAddBo.getName() + "'请填写居住地址");
                }
                customerGuarantor.setLoanId(loanId);
                customerGuarantorMapper.insert(customerGuarantor);
            }
        }

    }

    private void saveCustomerSpouse(@Valid CustomerSpouseAddBo customerSpouseAddBo,
        long customerId) {
        //参数验证
        if (null == customerSpouseAddBo) {
            throw new LoanParameterException("客户已婚，请填写配偶信息");
        }
        if (null == customerSpouseAddBo.getName() || null == customerSpouseAddBo.getIdCardNo()
            || null == customerSpouseAddBo.getMobile()) {
            throw new LoanParameterException("客户配偶信息必填项未填写完整");
        }
        String idCardNo = customerSpouseAddBo.getIdCardNo();
        if (!IdCardUtil.idCardValidate(idCardNo)) {
            throw new LoanParameterException("客户配偶身份证号码格式错误");
        }
        CustomerSpouse customerSpouse = new CustomerSpouse();
        BeanUtils.copyBeanProp(customerSpouse, customerSpouseAddBo);
        customerSpouse.setGuarantee(customerSpouseAddBo.getGuaranteeType());
        customerSpouse.setCustomerId(customerId);
        customerSpouseMapper.insert(customerSpouse);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public AjaxResult updateApply(LoanUpdateBo loanUpdateBo) {
        @NotNull Long loanId = loanUpdateBo.getId();
        Loan loan = loanMapper.selectById(loanId);
        if (null == loan) {
            return AjaxResult.error("不存在该业务");
        }
        //判断业务状态是否可提交
        Optional<LoanStatus> optionalLoanStatus = loanStatusMapper.selectByLoanId(loanId);
        LoanStatus loanStatus = optionalLoanStatus
            .orElseThrow(() -> new LoanParameterException("该业务状态数据异常，请联系管理员"));
        Long businessStatus = loanStatus.getBusinessStatus();
        Long businessAuditStatus = loanStatus.getBusinessAuditStatus();
        Long businessApostilleStatus = loanStatus.getBusinessApostilleStatus();
        if (LoanBusinessStatus.INIT.status != businessStatus
            && (LoanBusinessAuditStatus.GO_BACK.status != businessAuditStatus
            &&
            BusinessApostilleStatus.GO_BACK.status != businessApostilleStatus)) {
            return AjaxResult.error("当前状态无法修改");
        }
        //编辑客户信息
        saveCustomer(loanUpdateBo.getCustomerInfo(), loanId, loan.getCustomerId(), true);
        //编辑业务信息
        saveLoan(loanUpdateBo.getLoanInfo(), loanId, loan.getCustomerId(), true,
            loanUpdateBo.getOperatorStatus());

        //业务状态更新
        loanStatus.setBusinessStatus(loanUpdateBo.getOperatorStatus());
        loanStatus.setBusinessTime(LocalDateTime.now());
        loanStatus.setBusinessAuditStatus((long) LoanBusinessAuditStatus.INIT.status);
        loanStatus.setBusinessApostilleStatus((long) BusinessApostilleStatus.INIT.status);
        loanStatus.setBusinessAdminId(SecurityUtils.getLoginUserId());
        loanStatusMapper.updateById(loanStatus);
        return AjaxResult.success();
    }


    @Override
    public LoanContractAuditVo getContractAuditDetail(long loanId) {
        Optional<Loan> optionalLoan
            = Optional.ofNullable(loanMapper.selectById(loanId));
        Loan loan = optionalLoan.orElseThrow(() -> new LoanParameterException("无该业务数据"));
        LoanContractAuditVo loanContractAuditVo = new LoanContractAuditVo();
        //获取数据源
        Optional<LoanCar> optionalLoanCar = loanCarMapper.selectByLoanId(loanId);
        LoanCar loanCar = optionalLoanCar
            .orElseThrow(() -> new LoanParameterException("业务数据车辆信息异常"));
        Optional<LoanExt> optionalLoanExt = loanExtMapper.selectByLoanId(loanId);
        LoanExt loanExt = optionalLoanExt
            .orElseThrow(() -> new LoanParameterException("业务数据扩展信息异常"));
        Optional<LoanStatus> optionalLoanStatus = loanStatusMapper.selectByLoanId(loanId);
        LoanStatus loanStatus = optionalLoanStatus
            .orElseThrow(() -> new LoanParameterException("业务数据状态信息异常"));

        Optional<LoanDetail> optionalLoanDetail = loanDetailMapper.selectByLoanId(loanId);
        LoanDetail loanDetail = optionalLoanDetail
            .orElseThrow(() -> new LoanParameterException("业务数据详情信息异常"));

        //获取客户数据
        loanContractAuditVo.setCustomerInfo(getCustomerAddBo(loan.getId(), loan.getCustomerId()));
        //获取业务数据
        //基本信息获取
        loanContractAuditVo.setLoanBaseInfo(getLoanBaseInfoVo(loan));
        //业务信息
        loanContractAuditVo
            .setBusinessInfo(getBusinessInfoVo(loan, loanCar,
                loanExt, loanStatus, loanDetail));
        //获取附件信息
        List<LoanAlbum> loanAlbums = loanAlbumMapper.selectListByLoanId(loanId);
        Map<Integer, List<LoanAlbumBo>> loanAlbumMap = loanAlbums.stream().map(l -> {
            LoanAlbumBo loanAlbumBo = new LoanAlbumBo();
            if (LoanAlbumType.PDF.type == l.getType() || LoanAlbumType.VIDEOS.type == l.getType()) {
                loanAlbumBo.setUrl(qiniuUtil.getAuthUrlOriginalHttp(l.getUrl()));
            } else {
                loanAlbumBo.setUrl(qiniuUtil.getAdminAuthUrl(l.getUrl()));
                loanAlbumBo.setThumbnailUrl(qiniuUtil.getUrlByThumbnail(l.getUrl()));
            }
            loanAlbumBo.setLoanId(l.getLoanId());
            loanAlbumBo.setType(l.getType());
            loanAlbumBo.setDbUrl(l.getUrl());
            return loanAlbumBo;
        }).collect(Collectors.groupingBy(LoanAlbumBo::getType));
        loanContractAuditVo.setLoanAlbumMap(loanAlbumMap);
        //获取车辆评诂信息
        loanContractAuditVo.setCarEvaluations(getCarEvaluationInfo(loanCar.getFrameNo()));
        //获取征信信息
        //担保人，配偶，申请人
        List<CreditInfo> creditInfos = getCreditInfos(loanContractAuditVo.getCustomerInfo());
        loanContractAuditVo.setCreditInfos(creditInfos);
        //车辆信息
        LoanContractAuditVo.CarInfo carInfo = new LoanContractAuditVo.CarInfo();

        //保险信息
        LoanContractAuditVo.InsuranceInfo insuranceInfo = new LoanContractAuditVo.InsuranceInfo();
        Optional<LoanInsurance> loanInsuranceOptional = loanInsuranceMapper.selectByLoanId(loanId);
        BeanUtils.copyBeanProp(insuranceInfo, loanInsuranceOptional.get());
        loanContractAuditVo.setInsuranceInfo(insuranceInfo);

        BeanUtils.copyBeanProp(carInfo, loanCar);
        BeanUtils.copyBeanProp(carInfo, loanDetail);
        loanContractAuditVo.setCarInfo(carInfo);

        //详情备注
        BeanUtils.copyBeanProp(loanContractAuditVo, loanDetail);
        LoanContractAuditVo.FileInfo fileInfo = new FileInfo();
        fileInfo.setFileNo(loanDetail.getFileNo());
        loanContractAuditVo.setFileInfo(fileInfo);

        return loanContractAuditVo;
    }

    @Override
    public BusinessAuditDetailVo getBusinessAuditDetailVo(long loanId) {
        Optional<Loan> optionalLoan
            = Optional.ofNullable(loanMapper.selectById(loanId));
        Loan loan = optionalLoan.orElseThrow(() -> new LoanParameterException("无该业务数据"));
        BusinessAuditDetailVo businessAuditDetailVo = new BusinessAuditDetailVo();
        //获取数据源
        Optional<LoanCar> optionalLoanCar = loanCarMapper.selectByLoanId(loanId);
        LoanCar loanCar = optionalLoanCar
            .orElseThrow(() -> new LoanParameterException("业务数据车辆信息异常"));
        Optional<LoanExt> optionalLoanExt = loanExtMapper.selectByLoanId(loanId);
        LoanExt loanExt = optionalLoanExt
            .orElseThrow(() -> new LoanParameterException("业务数据扩展信息异常"));
        Optional<LoanStatus> optionalLoanStatus = loanStatusMapper.selectByLoanId(loanId);
        LoanStatus loanStatus = optionalLoanStatus
            .orElseThrow(() -> new LoanParameterException("业务数据状态信息异常"));

        Optional<LoanDetail> optionalLoanDetail = loanDetailMapper.selectByLoanId(loanId);
        LoanDetail loanDetail = optionalLoanDetail
            .orElseThrow(() -> new LoanParameterException("业务数据详情信息异常"));

        //获取客户数据
        businessAuditDetailVo.setCustomerInfo(getCustomerAddBo(loan.getId(), loan.getCustomerId()));
        //获取业务数据
        //基本信息获取
        businessAuditDetailVo.setLoanBaseInfo(getLoanBaseInfoVo(loan));
        //业务信息
        businessAuditDetailVo
            .setBusinessInfo(getBusinessInfoVo(loan, loanCar,
                loanExt, loanStatus, loanDetail));
        //获取附件信息
        List<LoanAlbum> loanAlbums = loanAlbumMapper.selectListByLoanId(loanId);
        Map<@NotNull Integer, List<LoanAlbumBo>> loanAlbumMap = loanAlbums.stream().map(l -> {
            LoanAlbumBo loanAlbumBo = new LoanAlbumBo();
            if (LoanAlbumType.PDF.type == l.getType() || LoanAlbumType.VIDEOS.type == l.getType()) {
                loanAlbumBo.setUrl(qiniuUtil.getAuthUrlOriginalHttp(l.getUrl()));
            } else {
                loanAlbumBo.setUrl(qiniuUtil.getAdminAuthUrl(l.getUrl()));
                loanAlbumBo.setThumbnailUrl(qiniuUtil.getUrlByThumbnail(l.getUrl()));
            }
            loanAlbumBo.setLoanId(l.getLoanId());
            loanAlbumBo.setType(l.getType());
            loanAlbumBo.setDbUrl(l.getUrl());
            return loanAlbumBo;
        }).collect(Collectors.groupingBy(LoanAlbumBo::getType));
        businessAuditDetailVo.setLoanAlbumMap(loanAlbumMap);

        //获取车辆评诂信息
        businessAuditDetailVo.setCarEvaluations(getCarEvaluationInfo(loanCar.getFrameNo()));
        //获取征信信息
        //担保人，配偶，申请人
        List<CreditInfo> creditInfos = getCreditInfos(businessAuditDetailVo.getCustomerInfo());
        businessAuditDetailVo.setCreditInfos(creditInfos);

        //业务审核数据获取
        BusinessAuditInfo businessAuditInfo = new BusinessAuditInfo();
        businessAuditInfo.setResult(loanStatus.getBusinessAuditStatus());
        businessAuditInfo.setBusinessAuditTime(loanStatus.getBusinessAuditTime());
        businessAuditInfo
            .setBusinessAuditName(redisDataUtil.getAdminName(loanStatus.getBusinessAuditId()));
        businessAuditInfo.setSecondAuditId(loan.getSecondAuditId());
        if (null != loan.getSecondAuditId() && loan.getSecondAuditId() > 0) {
            businessAuditInfo.setSecondResult(loanStatus.getBusinessApostilleStatus());
            SysUser admin = redisDataUtil.getAdmin(loan.getSecondAuditId());
            if (null != admin) {
                businessAuditInfo.setSecondAuditName(admin.getUserName());
                businessAuditInfo
                    .setSecondAuditDepName(redisDataUtil.getDeptName(admin.getDeptId()));
            }
        }

        businessAuditInfo.setAuditRemark(loanDetail.getAuditRemark());
        businessAuditInfo.setMissingRemark(loanDetail.getMissingRemark());
        businessAuditInfo.setBusinessSuggest(loanDetail.getBusinessSuggest());
        businessAuditInfo.setSecondAuditRemark(loanDetail.getSecondAuditRemark());
        businessAuditDetailVo.setBusinessAuditInfo(businessAuditInfo);

        //获取资料审核数据
        LoanDataAuditBo loanDataAuditBo = new LoanDataAuditBo();
        loanDataAuditBo.setLoanId(loan.getId().toString());
        loanDataAuditBo.setOperatorStatus(loanStatus.getDataAuditStatus());
        loanDataAuditBo.setDataTransferDate(loanDetail.getDataTransferDate());
        loanDataAuditBo.setMissingRemark(loanDetail.getMissingRemark());
        loanDataAuditBo.setDeductionCardNo(loanDetail.getDeductionCardNo());
        loanDataAuditBo.setSalesmanFinedAmount(loanDetail.getSalesmanFinedAmount());
        loanDataAuditBo.setSettleRemark(loanDetail.getSalesmanRemark());
        businessAuditDetailVo.setLoanDataAuditBo(loanDataAuditBo);
        BusinessAuditDetailVo.LoanStatusVo loanStatusVo = new BusinessAuditDetailVo.LoanStatusVo();
        loanStatusVo.setSettleAccountsStatus(loanStatus.getSettleAccountsStatus());
        businessAuditDetailVo.setLoanStatus(loanStatusVo);
        return businessAuditDetailVo;
    }

    public List<CreditInfo> getCreditInfos(CustomerAddBo customerInfo) {
        List<CreditInfo> creditInfos = Lists.newArrayList();

        Map<String, String> idCardMap = new HashMap<>();
        idCardMap.put(customerInfo.getCustomerInfo().getIdCardNo(), "申请人");

        if (CustomerMarry.MARRIED.status == customerInfo.getCustomerInfo().getMarry()) {
            idCardMap.put(customerInfo.getCustomerSpouse().getIdCardNo(), "配偶");
        }
        List<CustomerGuarantorAddBo> customerGuarantors = customerInfo.getCustomerGuarantors();
        if (StringUtils.isNotEmpty(customerGuarantors)) {
            idCardMap.putAll(customerGuarantors.stream()
                .collect(Collectors.toMap(CustomerGuarantorAddBo::getIdCardNo, c -> "担保人")));

        }
        CdCredit queryCredit = new CdCredit();
        queryCredit.setStatus(CreditStatus.COMPLETE.status);
        QueryWrapper<CdCredit> cdCreditQueryWrapper = new QueryWrapper<>(queryCredit);
        cdCreditQueryWrapper.in("id_card_no", idCardMap.keySet());
        List<CdCredit> cdCredits = cdCreditMapper.selectList(cdCreditQueryWrapper);
        if (StringUtils.isNotEmpty(cdCredits)) {
            creditInfos = cdCredits.stream().map(cdCredit -> {
                CreditInfo creditInfo = new CreditInfo();
                BeanUtils.copyBeanProp(creditInfo, cdCredit);
                creditInfo.setBankName(redisDataUtil.getBankName(cdCredit.getBankId()));
                creditInfo.setDeptName(redisDataUtil.getDeptName(cdCredit.getDeptId()));
                creditInfo.setAdminName(redisDataUtil.getAdminName(cdCredit.getAdminId()));
                creditInfo.setRelationship(idCardMap.get(cdCredit.getIdCardNo()));
                return creditInfo;
            }).collect(Collectors.toList());
        }
        return creditInfos;
    }

    public List<CarEvaluationInfo> getCarEvaluationInfo(String frameNo) {
        List<CarEvaluationInfo> carEvaluationInfos = Lists.newArrayList();
        if (StringUtils.isNotEmpty(frameNo)) {
            List<VeVehicleEvaluation> veVehicleEvaluations = veVehicleEvaluationMapper
                .findAllByFrameNo(frameNo);
            veVehicleEvaluations.forEach(veVehicleEvaluation -> {
                CarEvaluationInfo carEvaluationInfo = new CarEvaluationInfo();
                BeanUtils.copyBeanProp(carEvaluationInfo, veVehicleEvaluation);
                carEvaluationInfo
                    .setDeptName(redisDataUtil.getDeptName(veVehicleEvaluation.getDeptId()));
                carEvaluationInfo
                    .setAdminName(redisDataUtil.getAdminName(veVehicleEvaluation.getAdminId()));
                //评估附件
                List<VeVehicleAlbum> veVehicleAlbums = veVehicleAlbumMapper
                    .selectListByVehicleId(veVehicleEvaluation.getId());
                if (null != veVehicleAlbums && veVehicleAlbums.size() > 0) {
                    List<CreditAlbumVo> collect = veVehicleAlbums.stream()
                        .map(l -> new CreditAlbumVo().setId(l.getId())
                            .setUrl(qiniuUtil.getAdminAuthUrl(l.getUrl()))
                            .setThumbnailUrl(qiniuUtil.getUrlByThumbnail(l.getUrl()))
                            .setDbUrl(l.getUrl()))
                        .collect(Collectors.toList());
                    carEvaluationInfo.setVehicleAlbums(collect);
                }
                carEvaluationInfos.add(carEvaluationInfo);
            });
        }
        return carEvaluationInfos;
    }

    private BusinessInfoVo getBusinessInfoVo(Loan loan, LoanCar loanCar, LoanExt loanExt,
        LoanStatus loanStatus,
        LoanDetail loanDetail) {
        BusinessInfoVo businessInfo = new BusinessInfoVo();
        BeanUtils.copyBeanProp(businessInfo, loanCar);
        BeanUtils.copyBeanProp(businessInfo, loanExt);
        businessInfo.setCarType(loanCar.getCarType());
        businessInfo
            .setBankName(redisDataUtil.getBankName(loan.getBankId()));
        businessInfo.setContractDate(loanDetail.getContractDate());
        businessInfo.setBusinessSubmitTime(
            LocalDateUtil.parseDateTimeToString(loanStatus.getBusinessTime()));
        businessInfo
            .setBusinessSubmitName(redisDataUtil.getAdminName(loanStatus.getBusinessAdminId()));
        businessInfo.setRemark(loanDetail.getRemark());
        return businessInfo;
    }

    /**
     * 基本信息获取
     */
    public LoanBaseInfoVo getLoanBaseInfoVo(Loan loan) {
        LoanBaseInfoVo loanBaseInfoVo = new LoanBaseInfoVo();
        loanBaseInfoVo.setLoanNo(loan.getBusinessNo());
        loanBaseInfoVo
            .setDeptName(
                redisDataUtil.getDeptName(loan.getDeptId()));
        loanBaseInfoVo
            .setAdminName(
                redisDataUtil.getAdminName(loan.getAdminId()));
        loanBaseInfoVo
            .setDealerName(
                redisDataUtil.getDealerName(loan.getDealerId()));
        return loanBaseInfoVo;
    }


    @Override
    public LoanApplyVo getLoanApplyVo(long loanId) {
        //
        Optional<Loan> optionalLoan
            = Optional.ofNullable(loanMapper.selectById(loanId));
        Loan loan = optionalLoan.orElseThrow(() -> new LoanParameterException("无该业务数据"));
        LoanApplyVo loanApplyVo = new LoanApplyVo();
        loanApplyVo.setLoanId(loan.getId().toString());
        loanApplyVo.setLoanNo(loan.getBusinessNo());

        //获取业务数据
        loanApplyVo.setLoanInfo(getLoanAddBo(loan));

        //获取客户数据
        loanApplyVo.setCustomerInfo(getCustomerAddBo(loan.getId(), loan.getCustomerId()));
        return loanApplyVo;
    }

    private LoanAddBo getLoanAddBo(Loan loan) {
        Long loanId = loan.getId();
        LoanAddBo loanAddBo = new LoanAddBo();
        //获取基本数据
        LoanBaseAddBo loanBaseAddBo = new LoanBaseAddBo();
        BeanUtils.copyBeanProp(loanBaseAddBo, loan);
        loanBaseAddBo.setBankName(redisDataUtil.getBankName(loanBaseAddBo.getBankId()));
        loanBaseAddBo.setAdminName(redisDataUtil.getAdminName(loanBaseAddBo.getAdminId()));
        loanBaseAddBo.setDealerName(redisDataUtil.getDealerName(loanBaseAddBo.getDealerId()));
        loanBaseAddBo.setDeptName(redisDataUtil.getDeptName(loanBaseAddBo.getDeptId()));

        loanAddBo.setLoanBase(loanBaseAddBo);
        //获取车辆数据
        Optional<LoanCar> optionalLoanCar = loanCarMapper.selectByLoanId(loanId);
        LoanCar loanCar = optionalLoanCar
            .orElseThrow(() -> new LoanParameterException("该业务车辆数据异常，请联系管理员"));
        LoanAddCarBo loanAddCarBo = new LoanAddCarBo();
        BeanUtils.copyBeanProp(loanAddCarBo, loanCar);
        loanAddCarBo.setCarModel(loanCar.getType());
        loanAddBo.setLoanCar(loanAddCarBo);
        //获取附件及业务员备注
        LoanAddDetailBo loanAddDetailBo = new LoanAddDetailBo();
        Optional<LoanDetail> optionalLoanDetail = loanDetailMapper.selectByLoanId(loanId);
        LoanDetail loanDetail = optionalLoanDetail.orElse(new LoanDetail());
        loanAddDetailBo.setRemark(loanDetail.getRemark());

        loanAddBo.setAuditRemark(loanDetail.getAuditRemark());
        loanAddBo.setBusinessSuggest(loanDetail.getBusinessSuggest());
        loanAddBo.setMissingRemark(loanDetail.getMissingRemark());

        //附件
        List<LoanAlbum> loanAlbums = loanAlbumMapper.selectListByLoanId(loanId);
        if (StringUtils.isNotEmpty(loanAlbums)) {
            Map<Integer, List<LoanAlbum>> loanAlbumsMap = loanAlbums.stream()
                .collect(Collectors.groupingBy(LoanAlbum::getType));
            loanAddDetailBo
                .setContractImages(getCreditAlbumVos(loanAlbumsMap, LoanAlbumType.CONTRACT));
            loanAddDetailBo
                .setCreditImages(getCreditAlbumVos(loanAlbumsMap, LoanAlbumType.CREDIT));
            loanAddDetailBo
                .setFaceSignImages(getCreditAlbumVos(loanAlbumsMap, LoanAlbumType.FACE_SIGN));
            loanAddDetailBo
                .setHomeImages(getCreditAlbumVos(loanAlbumsMap, LoanAlbumType.HOME));
            loanAddDetailBo
                .setVideos(getCreditAlbumVosByOriginal(loanAlbumsMap, LoanAlbumType.VIDEOS));
            loanAddDetailBo.setPdf(getCreditAlbumVosByOriginal(loanAlbumsMap, LoanAlbumType.PDF));
        }
        loanAddBo.setLoanDetail(loanAddDetailBo);

        //获取业务金额信息
        LoanAddExtBo loanAddExtBo = new LoanAddExtBo();
        Optional<LoanExt> optionalLoanExt = loanExtMapper.selectByLoanId(loanId);
        LoanExt loanExt = optionalLoanExt
            .orElseThrow(() -> new LoanParameterException("该业务数据异常，请联系管理员"));
        BeanUtils.copyBeanProp(loanAddExtBo, loanExt);
        loanAddBo.setLoanExt(loanAddExtBo);
        return loanAddBo;
    }

    private List<CreditAlbumVo> getCreditAlbumVos(Map<Integer, List<LoanAlbum>> map,
        LoanAlbumType loanAlbumType) {
        List<LoanAlbum> loanAlbums = map.get(loanAlbumType.type);
        if (StringUtils.isNotEmpty(loanAlbums)) {
            return loanAlbums.stream()
                .map(l -> new CreditAlbumVo().setId(l.getId())
                    .setUrl(qiniuUtil.getAuthUrl(l.getUrl()))
                    .setThumbnailUrl(qiniuUtil.getUrlByThumbnailHttps(l.getUrl()))
                    .setDbUrl(l.getUrl()))
                .collect(Collectors.toList());
        }
        return Lists.newArrayList();
    }

    private List<CreditAlbumVo> getCreditAlbumVosByOriginal(Map<Integer, List<LoanAlbum>> map,
        LoanAlbumType loanAlbumType) {
        List<LoanAlbum> loanAlbums = map.get(loanAlbumType.type);
        if (StringUtils.isNotEmpty(loanAlbums)) {
            return loanAlbums.stream()
                .map(l -> new CreditAlbumVo().setId(l.getId())
                    .setUrl(qiniuUtil.getAuthUrlOriginal(l.getUrl()))
                    .setDbUrl(l.getUrl()))
                .collect(Collectors.toList());
        }
        return Lists.newArrayList();
    }


    public CustomerAddBo getCustomerAddBo(long loanId, long customerId) {
        CustomerAddBo customerAddBo = new CustomerAddBo();
        //客户基本信息
        CustomerInfoAddBo customerInfoAddBo = new CustomerInfoAddBo();
        Optional<Customer> optionalCustomer = Optional
            .ofNullable(customerMapper.selectById(customerId));
        Customer customer = optionalCustomer
            .orElseThrow(() -> new LoanParameterException("该业务客户数据异常，请联系管理员"));
        BeanUtils.copyBeanProp(customerInfoAddBo, customer);
        CustomerDetail customerDetail = customerDetailMapper.selectByCustomerId(customerId);
        BeanUtils.copyBeanProp(customerInfoAddBo, customerDetail);
        customerAddBo.setCustomerInfo(customerInfoAddBo);

        //客户联系人信息
        customerAddBo.setCustomerContacts(getCustomerContactAddBos(loanId));

        //客户配偶信息
        Integer marry = customer.getMarry();
        customerAddBo.setCustomerSpouse(new CustomerSpouseAddBo());
        if (CustomerMarry.MARRIED.status == marry) {
            Optional<CustomerSpouse> optionalCustomerSpouse = customerSpouseMapper
                .selectByCustomerId(customerId);
            CustomerSpouse customerSpouse = optionalCustomerSpouse.orElseThrow(() ->
                new LoanParameterException("该业务用户配偶数据异常，请联系管理员"));
            customerAddBo.getCustomerSpouse().setGuaranteeType(customerSpouse.getGuarantee());
            BeanUtils.copyBeanProp(customerAddBo.getCustomerSpouse(), customerSpouse);
        }
        //客户担保人信息
        customerAddBo.setCustomerGuarantors(getCustomerGuarantorAddBos(loanId));
        return customerAddBo;
    }

    private List<CustomerGuarantorAddBo> getCustomerGuarantorAddBos(long loanId) {
        List<CustomerGuarantor> customerGuarantors = customerGuarantorMapper
            .selectListByLoanId(loanId);
        if (StringUtils.isNotEmpty(customerGuarantors)) {
            return customerGuarantors.stream().map(l -> {
                CustomerGuarantorAddBo customerGuarantorAddBo = new CustomerGuarantorAddBo();
                BeanUtils.copyBeanProp(customerGuarantorAddBo, l);
                return customerGuarantorAddBo;
            }).collect(Collectors.toList());
        }
        return Lists.newArrayList();
    }

    private List<CustomerContactAddBo> getCustomerContactAddBos(long loanId) {
        List<LoanContact> loanContacts = loanContactMapper.selectListByLoanId(loanId);
        if (StringUtils.isNotEmpty(loanContacts)) {
            return loanContacts.stream().map(l -> {
                CustomerContactAddBo customerContactAddBo = new CustomerContactAddBo();
                BeanUtils.copyBeanProp(customerContactAddBo, l);
                return customerContactAddBo;
            }).collect(Collectors.toList());
        }
        return Lists.newArrayList();
    }


    /**
     * 查询贷款列表
     *
     * @param loan 贷款
     * @return 贷款
     */
    @Override
    public List<Loan> selectLoanList(Loan loan) {
        QueryWrapper<Loan> queryWrapper = new QueryWrapper<>(loan);
        return loanMapper.selectList(queryWrapper);
    }


    @Override
    public IPage<Loan> selectPage(IPage<Loan> page, QueryWrapper<Loan> queryWrapper) {
        return loanMapper.selectPage(page, queryWrapper);
    }

    /**
     * 新增贷款
     *
     * @param loan 贷款
     * @return 结果
     */
    @Override
    public int insertLoan(Loan loan) {

        return loanMapper.insert(loan);
    }

    /**
     * 修改贷款
     *
     * @param loan 贷款
     * @return 结果
     */
    @Override
    public int updateLoan(Loan loan) {

        return loanMapper.updateById(loan);
    }

    /**
     * 删除贷款对象
     *
     * @param ids 需要删除的数据ID
     * @return 结果
     */
    @Override
    public int deleteLoanByIds(Collection<Long> ids) {
        return loanMapper.deleteBatchIds(ids);
    }

    /**
     * 删除贷款信息
     *
     * @param id 贷款ID
     * @return 结果
     */
    @Override
    public int deleteLoanById(Long id) {
        return loanMapper.deleteById(id);
    }

    @Override
    public BusinessDetailVo businessDetail(Long loanId) {
        Optional<Loan> optionalLoan
            = Optional.ofNullable(loanMapper.selectById(loanId));
        Loan loan = optionalLoan.orElseThrow(() -> new LoanParameterException("无该业务数据"));
        BusinessDetailVo businessDetailVo = new BusinessDetailVo();
        //获取数据源
        Optional<LoanCar> optionalLoanCar = loanCarMapper.selectByLoanId(loanId);
        LoanCar loanCar = optionalLoanCar
            .orElseThrow(() -> new LoanParameterException("业务数据车辆信息异常"));
        Optional<LoanExt> optionalLoanExt = loanExtMapper.selectByLoanId(loanId);
        LoanExt loanExt = optionalLoanExt
            .orElseThrow(() -> new LoanParameterException("业务数据扩展信息异常"));
        Optional<LoanDetail> optionalLoanDetail = loanDetailMapper.selectByLoanId(loanId);
        LoanDetail loanDetail = optionalLoanDetail
            .orElseThrow(() -> new LoanParameterException("业务数据详情信息异常"));

        //获取客户数据
        businessDetailVo.setCustomerInfo(getCustomerAddBo(loan.getId(), loan.getCustomerId()));
        //业务基本信息获取
        businessDetailVo.setLoanBaseInfo(getLoanBaseInfoVo(loan));
        //业务信息
        BusinessDetailVo.LoanInfo loanInfo = new BusinessDetailVo.LoanInfo();
        BeanUtils.copyBeanProp(loanInfo, loanDetail);
        loanInfo.setBankName(redisDataUtil.getBankName(loan.getBankId()));
        loanInfo.setInstallmentAmount(loanExt.getInstallmentAmount());
        loanInfo.setRate(loanExt.getRate());
        loanInfo.setFinancingAmount(loanExt.getFinancingAmount());
        loanInfo.setTerm(loanExt.getTerm());
        businessDetailVo.setLoanInfo(loanInfo);
        //车辆信息
        BusinessDetailVo.CarInfo carInfo = new BusinessDetailVo.CarInfo();
        BeanUtils.copyBeanProp(carInfo, loanCar);
        businessDetailVo.setCarInfo(carInfo);
        return businessDetailVo;
    }


    @Override
    @Transactional(rollbackFor = Exception.class)
    public synchronized AjaxResult modifyBusiness(LoanModifyBo loanModifyBo) {
        long loanId = Long.parseLong(loanModifyBo.getLoanId());
        LoanModifyDetail loanModifyDetail = new LoanModifyDetail();
        Optional<Loan> optionalLoan
            = Optional.ofNullable(loanMapper.selectById(loanId));
        Loan loan = optionalLoan.orElseThrow(() -> new LoanParameterException("无该业务数据"));
        //获取数据源
        Optional<LoanCar> optionalLoanCar = loanCarMapper.selectByLoanId(loanId);
        LoanCar loanCar = optionalLoanCar
            .orElseThrow(() -> new LoanParameterException("业务数据车辆信息异常"));
        Optional<LoanExt> optionalLoanExt = loanExtMapper.selectByLoanId(loanId);
        LoanExt loanExt = optionalLoanExt
            .orElseThrow(() -> new LoanParameterException("业务数据扩展信息异常"));
        Optional<LoanStatus> optionalLoanStatus = loanStatusMapper.selectByLoanId(loanId);
        LoanStatus loanStatus = optionalLoanStatus
            .orElseThrow(() -> new LoanParameterException("业务数据状态信息异常"));

        //基本信息
        BaseInfo baseInfo = new BaseInfo();
        baseInfo.setBusinessNo(loan.getBusinessNo());
        baseInfo.setDeptId(loan.getDeptId());
        baseInfo.setDeptName(redisDataUtil.getDeptName(loan.getDeptId()));
        baseInfo.setAdminId(loan.getAdminId());
        baseInfo.setAdminName(redisDataUtil.getAdminName(loan.getAdminId()));
        baseInfo.setDealerId(loan.getDealerId());
        baseInfo.setDealerName(redisDataUtil.getDealerName(loan.getDealerId()));
        loanModifyDetail.setBaseInfo(baseInfo);

        //业务信息
        BusinessInfo businessInfo = new BusinessInfo();
        businessInfo.setBankName(redisDataUtil.getBankName(loan.getBankId()));
        businessInfo.setBankId(loan.getBankId());
        businessInfo.setBankSchemeId(loan.getBankSchemeId());
        CmBankScheme cmBankScheme = cmBankSchemeMapper.selectById(loan.getBankSchemeId());
        businessInfo.setBankTypeId(cmBankScheme.getBankCarTypeId());
        businessInfo.setCarType(loanCar.getCarType());
        businessInfo.setCarNature(loanCar.getCarNature());
        businessInfo.setInstallmentAmount(loanExt.getInstallmentAmount());
        businessInfo.setTerm(loanExt.getTerm());
        businessInfo.setBankRate(loanExt.getBankRate());
        businessInfo.setFinancingAmount(loanExt.getFinancingAmount());
        loanModifyDetail.setBusinessInfo(businessInfo);

        //还款信息
        Optional<LoanDetail> optionalLoanDetail = loanDetailMapper.selectByLoanId(loanId);
        LoanDetail loanDetail = optionalLoanDetail
            .orElseThrow(() -> new LoanParameterException("业务数据详情信息异常"));
        if (RepaymentInfoStatus.SUBMIT.status == loanStatus.getRepaymentInfoStatus()) {
            LoanModifyDetail.RepayInfo repayInfo = new RepayInfo();
            repayInfo.setRepayCardNo(loanDetail.getRepayCardNo());
            repayInfo.setDeductionCardNo(loanDetail.getDeductionCardNo());
            loanModifyDetail.setRepayInfo(repayInfo);
        }
        Long loanDetailId = loanDetail.getId();
        //客户基本信息
        Optional<Customer> optionalCustomer = Optional
            .ofNullable(customerMapper.selectById(loan.getCustomerId()));
        Customer customer = optionalCustomer
            .orElseThrow(() -> new LoanParameterException("该业务客户数据异常，请联系管理员"));
        CustomerDetail customerDetail = customerDetailMapper.selectByCustomerId(customer.getId());
        CustomerInfo customerInfo = new CustomerInfo();
        BeanUtils.copyBeanProp(customerInfo, customerDetail);
        customerInfo.setName(customer.getName());
        customerInfo.setIdCardNo(customer.getIdCardNo());
        customerInfo.setIdType(customer.getIdType());
        customerInfo.setMobile(customer.getMobile());
        loanModifyDetail.setCustomerInfo(customerInfo);

        //修改还款计划
        BusinessInfo businessInfoModify = loanModifyBo.getBusinessInfo();
        CmBank cmBank = cmBankMapper.selectById(businessInfoModify.getBankId());
        RepaymentFormulaInterface repaymentFormulaInterface = repaymentFormulaInterfaceMap
            .get(cmBank.getRepaymentFormula());

        Integer financingAmount = repaymentFormulaInterface
            .getFinancingAmount(new BigDecimal(businessInfoModify.getInstallmentAmount()),
                new BigDecimal(businessInfoModify.getRate()),
                new BigDecimal(businessInfoModify.getBankRate()));

        //客户配偶信息
        Integer marry = customer.getMarry();
        Long customerSpouseId = null;
        if (CustomerMarry.MARRIED.status == marry) {
            Optional<CustomerSpouse> optionalCustomerSpouse = customerSpouseMapper
                .selectByCustomerId(customer.getId());
            CustomerSpouse customerSpouse = optionalCustomerSpouse.orElseThrow(() ->
                new LoanParameterException("该业务用户配偶数据异常，请联系管理员"));
            loanModifyDetail.setCustomerSpouse(customerSpouse);
            customerSpouseId = customerSpouse.getId();

        }
        //客户担保人信息
        List<CustomerGuarantor> customerGuarantors = customerGuarantorMapper
            .selectListByLoanId(loanId);
        if (null != customerGuarantors && customerGuarantors.size() > 0) {
            loanModifyDetail.setCustomerGuarantorInfos(customerGuarantors);
        }

        //联系人信息
        List<LoanContact> loanContacts = loanContactMapper.selectListByLoanId(loanId);
        if (null != loanContacts && loanContacts.size() > 0) {
            loanModifyDetail.setCustomerContactInfos(loanContacts);
        }

        List<LoanModifyFiledBo> loanModifyFiledBos = LoanModifyInfoBo
            .getLoanModifyFiledBos(loanModifyBo, loanModifyDetail);

        //处理修改信息
        //担保人和联系人特殊判断
        List<LoanContact> oldCustomerContactInfos = loanModifyDetail.getCustomerContactInfos();
        List<LoanContact> newCustomerContactInfos = loanModifyBo.getCustomerContactInfos();
        if (oldCustomerContactInfos.size() != newCustomerContactInfos.size()) {
            return AjaxResult.error("联系人个数不一致，请检查数据");
        }
        //id对比
        Map<Long, LoanContact> oldCustomerContactInfoMap = oldCustomerContactInfos.stream()
            .collect(Collectors.toMap(LoanContact::getId, loanContact -> loanContact));

        AtomicInteger atomicContactCount = new AtomicInteger();
        newCustomerContactInfos.forEach(newCustomerContactInfo -> {
            LoanContact loanContact = oldCustomerContactInfoMap.get(newCustomerContactInfo.getId());
            if (null == loanContact) {
                throw new LoanParameterException("联系人id未填写");
            }
            loanModifyFiledBos.addAll(LoanModifyInfoBo
                .getLoanModifyFiledBos(newCustomerContactInfo, loanContact,
                    "联系人信息" + atomicContactCount.addAndGet(1)));
        });

        List<CustomerGuarantor> oldCustomerGuarantorInfos = loanModifyDetail
            .getCustomerGuarantorInfos();
        List<CustomerGuarantor> newCustomerGuarantorInfos = loanModifyBo
            .getCustomerGuarantorInfos();
        if (oldCustomerGuarantorInfos.size() != newCustomerGuarantorInfos.size()) {
            return AjaxResult.error("担保人个数不一致，请检查数据");
        }
        Map<Long, CustomerGuarantor> oldCustomerGuarantorInfoMap = oldCustomerGuarantorInfos
            .stream()
            .collect(Collectors.toMap(CustomerGuarantor::getId, c -> c));

        AtomicInteger atomicGuarantorCount = new AtomicInteger();
        newCustomerGuarantorInfos.forEach(newCustomerGuarantor -> {
            CustomerGuarantor customerGuarantor = oldCustomerGuarantorInfoMap
                .get(newCustomerGuarantor.getId());
            if (null == customerGuarantor) {
                throw new LoanParameterException("担保人id未填写");
            }
            loanModifyFiledBos.addAll(LoanModifyInfoBo
                .getLoanModifyFiledBos(newCustomerGuarantor, customerGuarantor,
                    "担保人信息" + atomicGuarantorCount.addAndGet(1)));
        });
        if (loanModifyFiledBos.size() == 0) {
            return AjaxResult.error("无修改信息");
        }

        //更新基本信息 和业务信息
        BaseInfo baseInfoModify = loanModifyBo.getBaseInfo();
        Loan loanModify = new Loan();
        loanModify.setDealerId(baseInfoModify.getDealerId());
        loanModify.setDeptId(baseInfoModify.getDeptId());
        loanModify.setAdminId(baseInfoModify.getAdminId());
        loanModify.setBankId(businessInfoModify.getBankId());
        loanModify.setBankSchemeId(businessInfoModify.getBankSchemeId());
        loanModify.setId(loanId);
        loanMapper.updateById(loanModify);

        LoanCar loanCarModify = new LoanCar();
        loanCarModify.setCarNature(businessInfoModify.getCarNature());
        loanCarModify.setCarType(businessInfoModify.getCarType());
        loanCarModify.setId(loanCar.getId());
        loanCarMapper.updateById(loanCarModify);

        LoanExt loanExtModify = new LoanExt();
        loanExtModify.setInstallmentAmount(businessInfoModify.getInstallmentAmount());
        loanExtModify.setFinancingAmount(Double.parseDouble(financingAmount.toString()));
        loanExtModify.setBankRate(businessInfoModify.getBankRate());
        loanExtModify.setTerm(businessInfoModify.getTerm());
        loanExtModify.setId(loanExt.getId());
        loanExtMapper.updateById(loanExtModify);
        if (RepaymentInfoStatus.SUBMIT.status == loanStatus.getRepaymentInfoStatus()) {
            RepaymentInfoParam repaymentInfoParam = new RepaymentInfoParam();
            repaymentInfoParam
                .setFinancingAmount(new BigDecimal(loanExtModify.getFinancingAmount()));
            repaymentInfoParam
                .setInstallmentAmount(new BigDecimal(loanExtModify.getInstallmentAmount()));
            repaymentInfoParam
                .setRate(new BigDecimal(loanExtModify.getBankRate())
                    .divide(new BigDecimal(100), MathContext.DECIMAL128));
            repaymentInfoParam.setTerm(Integer.valueOf(loanExtModify.getTerm().toString()));
            RepaymentInfo repaymentInfo = repaymentFormulaInterface
                .getRepaymentInfo(repaymentInfoParam);
            loanDetail.setMonthRepayInterest(repaymentInfo.getMonthRepayInterest());
            loanDetail.setMonthRepayPrincipal(repaymentInfo.getMonthRepayPrincipal());
            loanDetail.setFirstRepayInterest(repaymentInfo.getFirstRepayInterest());
            loanDetail.setFirstRepayPrincipal(repaymentInfo.getFirstRepayPrincipal());
            loanDetail.setLastRepayInterest(repaymentInfo.getLastRepayInterest());
            loanDetail.setLastRepayPrincipal(repaymentInfo.getLastRepayPrincipal());
            loanDetail.setLastRepaymentDate(repaymentInfo.getLastRepaymentDate());
        }
        loanDetail.setId(loanDetailId);
        //还款信息
        if (RepaymentInfoStatus.SUBMIT.status == loanStatus.getRepaymentInfoStatus()) {
            RepayInfo repayInfoModify = loanModifyBo.getRepayInfo();
            loanDetail.setRepayCardNo(repayInfoModify.getRepayCardNo());
            loanDetail.setDeductionCardNo(repayInfoModify.getDeductionCardNo());
        }
        loanDetailMapper.updateById(loanDetail);

        //借款人信息
        CustomerInfo customerInfoModify = loanModifyBo.getCustomerInfo();
        Customer customerModify = new Customer();
        customerModify.setMobile(customerInfoModify.getMobile());
        customerModify.setIdType(customerInfoModify.getIdType());
        customerModify.setIdCardNo(customerInfoModify.getIdCardNo());
        customerModify.setId(loan.getCustomerId());
        customerMapper.updateById(customerModify);

        CustomerDetail customerDetailModify = new CustomerDetail();
        BeanUtils.copyBeanProp(customerDetailModify, customerInfoModify);
        customerDetailModify.setId(customerDetail.getId());
        customerDetailMapper.updateById(customerDetailModify);

        //配偶信息
        if (CustomerMarry.MARRIED.status == marry) {
            CustomerSpouse customerSpouseModify = new CustomerSpouse();
            BeanUtils.copyBeanProp(customerSpouseModify, loanModifyBo.getCustomerSpouse());
            customerSpouseModify.setId(customerSpouseId);
            customerSpouseModify.setCustomerId(null);
            customerSpouseMapper.updateById(customerSpouseModify);
        }
        //担保人 联系人修改
        //id对比
        newCustomerContactInfos.forEach(newCustomerContactInfo -> {
            newCustomerContactInfo.setLoanId(null);
            loanContactMapper.updateById(newCustomerContactInfo);
        });
        newCustomerGuarantorInfos.forEach(newCustomerGuarantor -> {
            newCustomerGuarantor.setLoanId(null);
            customerGuarantorMapper.updateById(newCustomerGuarantor);
        });
        LoanModifyInfo loanModifyInfo = new LoanModifyInfo();
        loanModifyInfo.setLoanId(Long.parseLong(loanModifyBo.getLoanId()));
        loanModifyInfo.setModifyTime(LocalDateTime.now());
        loanModifyInfo.setModifyId(Integer.parseInt(SecurityUtils.getLoginUserId().toString()));
        loanModifyInfo.setModifyRemark(loanModifyBo.getModifyRemark());
        loanModifyInfo.setModifyContent(JSON.toJSONString(loanModifyFiledBos));
        loanModifyInfoMapper.insert(loanModifyInfo);
        return AjaxResult.success();
    }

    @Resource
    private LoanModifyInfoMapper loanModifyInfoMapper;

    @Override
    public LoanModifyDetail getModifyDetail(Long loanId) {

        LoanModifyDetail loanModifyDetail = new LoanModifyDetail();

        Optional<Loan> optionalLoan
            = Optional.ofNullable(loanMapper.selectById(loanId));
        Loan loan = optionalLoan.orElseThrow(() -> new LoanParameterException("无该业务数据"));
        //获取数据源
        Optional<LoanCar> optionalLoanCar = loanCarMapper.selectByLoanId(loanId);
        LoanCar loanCar = optionalLoanCar
            .orElseThrow(() -> new LoanParameterException("业务数据车辆信息异常"));
        Optional<LoanExt> optionalLoanExt = loanExtMapper.selectByLoanId(loanId);
        LoanExt loanExt = optionalLoanExt
            .orElseThrow(() -> new LoanParameterException("业务数据扩展信息异常"));
        Optional<LoanStatus> optionalLoanStatus = loanStatusMapper.selectByLoanId(loanId);
        LoanStatus loanStatus = optionalLoanStatus
            .orElseThrow(() -> new LoanParameterException("业务数据状态信息异常"));

        //基本信息
        BaseInfo baseInfo = new BaseInfo();
        baseInfo.setBusinessNo(loan.getBusinessNo());
        baseInfo.setDeptId(loan.getDeptId());
        baseInfo.setDeptName(redisDataUtil.getDeptName(loan.getDeptId()));
        baseInfo.setAdminId(loan.getAdminId());
        baseInfo.setAdminName(redisDataUtil.getAdminName(loan.getAdminId()));
        baseInfo.setDealerId(loan.getDealerId());
        baseInfo.setDealerName(redisDataUtil.getDealerName(loan.getDealerId()));
        loanModifyDetail.setBaseInfo(baseInfo);

        //业务信息
        BusinessInfo businessInfo = new BusinessInfo();
        businessInfo.setBankName(redisDataUtil.getBankName(loan.getBankId()));
        businessInfo.setBankId(loan.getBankId());
        businessInfo.setBankSchemeId(loan.getBankSchemeId());
        CmBankScheme cmBankScheme = cmBankSchemeMapper.selectById(loan.getBankSchemeId());
        businessInfo.setBankTypeId(cmBankScheme.getBankCarTypeId());
        businessInfo.setCarType(loanCar.getCarType());
        businessInfo.setCarNature(loanCar.getCarNature());
        businessInfo.setInstallmentAmount(loanExt.getInstallmentAmount());
        businessInfo.setTerm(loanExt.getTerm());
        businessInfo.setBankRate(loanExt.getBankRate());
        businessInfo.setRate(loanExt.getRate());
        businessInfo.setFinancingAmount(loanExt.getFinancingAmount());
        loanModifyDetail.setBusinessInfo(businessInfo);

        //还款信息
        if (RepaymentInfoStatus.SUBMIT.status == loanStatus.getRepaymentInfoStatus()) {
            Optional<LoanDetail> optionalLoanDetail = loanDetailMapper.selectByLoanId(loanId);
            LoanDetail loanDetail = optionalLoanDetail
                .orElseThrow(() -> new LoanParameterException("业务数据详情信息异常"));
            LoanModifyDetail.RepayInfo repayInfo = new RepayInfo();
            repayInfo.setRepayCardNo(loanDetail.getRepayCardNo());
            repayInfo.setDeductionCardNo(loanDetail.getDeductionCardNo());
            loanModifyDetail.setRepayInfo(repayInfo);
        }

        //客户基本信息
        Optional<Customer> optionalCustomer = Optional
            .ofNullable(customerMapper.selectById(loan.getCustomerId()));
        Customer customer = optionalCustomer
            .orElseThrow(() -> new LoanParameterException("该业务客户数据异常，请联系管理员"));
        CustomerDetail customerDetail = customerDetailMapper.selectByCustomerId(customer.getId());
        CustomerInfo customerInfo = new CustomerInfo();
        BeanUtils.copyBeanProp(customerInfo, customerDetail);
        customerInfo.setMarry(customer.getMarry());
        customerInfo.setName(customer.getName());
        customerInfo.setIdCardNo(customer.getIdCardNo());
        customerInfo.setIdType(customer.getIdType());
        customerInfo.setMobile(customer.getMobile());
        loanModifyDetail.setCustomerInfo(customerInfo);
        //客户配偶信息
        Integer marry = customer.getMarry();
        if (CustomerMarry.MARRIED.status == marry) {
            Optional<CustomerSpouse> optionalCustomerSpouse = customerSpouseMapper
                .selectByCustomerId(customer.getId());
            CustomerSpouse customerSpouse = optionalCustomerSpouse.orElseThrow(() ->
                new LoanParameterException("该业务用户配偶数据异常，请联系管理员"));
            loanModifyDetail.setCustomerSpouse(customerSpouse);

        }
        //客户担保人信息
        List<CustomerGuarantor> customerGuarantors = customerGuarantorMapper
            .selectListByLoanId(loanId);
        if (null != customerGuarantors && customerGuarantors.size() > 0) {
            loanModifyDetail.setCustomerGuarantorInfos(customerGuarantors);
        }

        //联系人信息
        List<LoanContact> loanContacts = loanContactMapper.selectListByLoanId(loanId);
        if (null != loanContacts && loanContacts.size() > 0) {
            loanModifyDetail.setCustomerContactInfos(loanContacts);
        }
        Map<String, SysUser> redisUserMap = redisDataUtil.getRedisUserMap();
        //修改信息
        List<LoanModifyInfo> loanModifyInfos = loanModifyInfoMapper.selectByLoanId(loanId);
        if (null != loanModifyInfos && loanModifyInfos.size() > 0) {
            List<LoanModifyInfoBo> collect = loanModifyInfos.stream()
                .map(loanModifyInfo -> LoanModifyInfoBo.transform(loanModifyInfo, redisUserMap))
                .collect(Collectors.toList());
            loanModifyDetail.setLoanModifyInfos(collect);
        }
        //获取附件
        List<LoanAlbum> loanAlbums = loanAlbumMapper.selectListByLoanId(loanId);
        Map<@NotNull Integer, List<LoanAlbumVo>> loanAlbumMap = loanAlbums.stream().map(l -> {
            LoanAlbumVo loanAlbumBo = new LoanAlbumVo();
            if (LoanAlbumType.PDF.type == l.getType() || LoanAlbumType.VIDEOS.type == l.getType()) {
                loanAlbumBo.setUrl(qiniuUtil.getAuthUrlOriginalHttp(l.getUrl()));
            } else {
                loanAlbumBo.setUrl(qiniuUtil.getAdminAuthUrl(l.getUrl()));
                loanAlbumBo.setThumbnailUrl(qiniuUtil.getUrlByThumbnail(l.getUrl()));
            }
            loanAlbumBo.setLoanId(l.getLoanId());
            loanAlbumBo.setType(l.getType());
            loanAlbumBo.setId(l.getId());
            loanAlbumBo.setDbUrl(l.getUrl());
            return loanAlbumBo;
        }).collect(Collectors.groupingBy(LoanAlbumVo::getType));
        loanModifyDetail.setLoanAlbumMap(loanAlbumMap);

        return loanModifyDetail;
    }
}
